local extension = Package("dajubei")
extension.extensionName = "tuntian_studio"

local U = require "packages/utility/utility"
local TT = require "packages/tuntian_studio/utility"
local DIY = require "packages/diy_utility/diy_utility"

Fk:loadTranslationTable{
  ["dajubei"] = "大剧杯",
  ["djb1"] = "大剧杯",
  ["djb2"] = "大剧杯",
}

local stormspirit = General(extension, "stormspirit", "west", 4)
local chaofuhe = fk.CreateTriggerSkill{
  name = "dajubei__chaofuhe",
  anim_type = "control",
  events = {fk.CardUseFinished},
  can_trigger = function(self, event, target, player, data)
    return target == player and player:hasSkill(self) and data.card.type == Card.TypeBasic and
      table.find(player.room:getOtherPlayers(player), function (p)
        return not p:isNude()
      end)
  end,
  on_cost = function(self, event, target, player, data)
    local room = player.room
    local targets = table.filter(room:getOtherPlayers(player), function (p)
      return not p:isNude()
    end)
    local to = player.room:askForChoosePlayers(player, table.map(targets, Util.IdMapper), 1, 1,
      "#dajubei__chaofuhe-choose", self.name, true)
    if #to > 0 then
      self.cost_data = {tos = to}
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local to = room:getPlayerById(self.cost_data.tos[1])
    local cards = to:getCardIds("e")
    table.insertTable(cards, table.filter(to:getCardIds("h"), function (id)
      return not to:prohibitDiscard(id)
    end))
    local card = room:askForCard(to, 1, 1, true, self.name, false, tostring(Exppattern{ id = cards }), "#dajubei__chaofuhe-card")
    if table.contains(to:getCardIds("h"), card[1]) then
      room:throwCard(card, self.name, to, to)
    else
      room:moveCardTo(card, Card.PlayerHand, to, fk.ReasonJustMove, self.name, nil, true, to.id)
    end
  end,
}
local qiuzhuangshandian = fk.CreateActiveSkill{
  name = "dajubei__qiuzhuangshandian",
  anim_type = "drawcard",
  card_num = 0,
  target_num = 0,
  prompt = "#dajubei__qiuzhuangshandian",
  can_use = function(self, player)
    return player:usedSkillTimes(self.name, Player.HistoryPhase) == 0 and
      table.find(Fk:currentRoom().alive_players, function (p)
        return p:getHandcardNum() - player:getHandcardNum() == 1
      end)
  end,
  card_filter = Util.FalseFunc,
  on_use = function(self, room, effect)
    local player = room:getPlayerById(effect.from)
    player:drawCards(1, self.name)
    while not player.dead and table.find(room.alive_players, function (p)
      return p:getHandcardNum() - player:getHandcardNum() == 1
    end) and room:askForSkillInvoke(player, self.name, nil, "#dajubei__qiuzhuangshandian") do
      player:drawCards(1, self.name)
    end
  end,
}
stormspirit:addSkill(chaofuhe)
stormspirit:addSkill(qiuzhuangshandian)
Fk:loadTranslationTable{
  ["stormspirit"] = "风暴之灵",
  ["#stormspirit"] = "蓝猫",
  ["illustrator:stormspirit"] = "DOTA",
  ["designer:stormspirit"] = "好孩子系我",

  ["dajubei__chaofuhe"] = "超负荷",
  [":dajubei__chaofuhe"] = "当你使用一张基本牌后，你可令一名其他角色选择一项：1.收回一张装备牌；2.弃置一张手牌。",
  ["dajubei__qiuzhuangshandian"] = "球状闪电",
  [":dajubei__qiuzhuangshandian"] = "出牌阶段限一次，你可以重复此流程：若有角色手牌比你多一张，你可以摸一张牌。",
  ["#dajubei__chaofuhe-choose"] = "超负荷：你可以令一名其他角色选择收回一张装备或弃置一张手牌",
  ["#dajubei__chaofuhe-card"] = "超负荷：请收回一张装备，或弃置一张手牌",
  ["#dajubei__qiuzhuangshandian"] = "球状闪电：是否摸一张牌？",

  ["$dajubei__chaofuhe1"] = "给你留点东西~",
  ["$dajubei__chaofuhe2"] = "唔，那个怪叔叔是谁？",
  ["$dajubei__qiuzhuangshandian1"] = "为台风做好准备吧！",
  ["$dajubei__qiuzhuangshandian2"] = "风暴时间！",

  ["$stormspirit_win_audio"] = "这才是风暴之灵！",
  ["~stormspirit"] = "我，无法呼吸了……",
}

Fk:addPoxiMethod{
  name = "shehu_delay",
  card_filter = function(to_select, selected, data)
    local s = Fk:getCardById(to_select).suit
    for _, id in ipairs(selected) do
      if Fk:getCardById(id).suit == s then return false end
    end
    return true
  end,
  feasible = function(selected, data)
    return #selected > 0
  end,
  prompt = "慑胡：选择任意数量花色各不同的牌"
}

local liguang = General(extension, "dajubei__liguang", "han", 4)
local yingong = fk.CreateTriggerSkill{
  name = "dajubei__yingong",
  anim_type = "special",
  frequency = Skill.Compulsory,
  events = {fk.AfterCardsMove},
  can_trigger = function(self, event, target, player, data)
    if player:hasSkill(self) and player:getMark("@@dajubei__yingong") == 0 then
      for _, move in ipairs(data) do
        if move.toArea == Card.DiscardPile then
          return true
        end
      end
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local n = 0
    for _, move in ipairs(data) do
      if move.toArea == Card.DiscardPile then
        n = n + #move.moveInfo
      end
    end
    room:addPlayerMark(player, "@dajubei__yingong-turn", n)
    if table.every(room:getOtherPlayers(player), function (p)
      return player:inMyAttackRange(p) end) and room:getBanner("@$CenterArea") then
      local cards = table.filter(room:getBanner("@$CenterArea"), function (id) return Fk:getCardById(id).trueName == "slash" end)
      local use = U.askForUseRealCard(room, player, cards, nil, self.name, "#djb__yingong-use",
        {expand_pile = cards, bypass_times = true}, true, true)
      if use then
        room:addPlayerMark(player, "@@dajubei__yingong")
        room:useCard(use)
      end
    end
  end,

  refresh_events = {fk.BeforeTurnStart},
  can_refresh = function(self, event, target, player, data)
    return target == player and player:getMark("@@dajubei__yingong") > 0
  end,
  on_refresh = function(self, event, target, player, data)
    player.room:setPlayerMark(player, "@@dajubei__yingong", 0)
  end,
}
local yingong_attackrange = fk.CreateAttackRangeSkill{
  name = "#dajubei__yingong_attackrange",
  frequency = Skill.Compulsory,
  correct_func = function (self, from, to)
    return from:getMark("@dajubei__yingong-turn")
  end,
}
local shehu = fk.CreateTriggerSkill{
  name = "dajubei__shehu",
  anim_type = "offensive",
  events = {fk.TargetSpecified},
  can_trigger = function(self, event, target, player, data)
    return target == player and player:hasSkill(self) and data.card.trueName == "slash" and
    player:usedSkillTimes(self.name) == 0 and not player.room:getPlayerById(data.to).dead
  end,
  on_cost = function (self, event, target, player, data)
    return player.room:askForSkillInvoke(player, self.name, nil, "#dajubei__shehu-invoke::"..data.to)
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local to = room:getPlayerById(data.to)
    local cards = room:getNCards(player:distanceTo(to))
    data.extra_data = data.extra_data or {}
    data.extra_data.dajubei__shehu = {player.id, cards}
    room:moveCardTo(cards, Card.Processing, nil, fk.ReasonJustMove, self.name, nil, true, player.id)
    if table.every(cards, function (id)
      --return data.card:compareSuitWith(Fk:getCardById(id), true)
      return data.card.suit ~= Fk:getCardById(id).suit
    end) then
      data.disresponsiveList = data.disresponsiveList or {}
      table.insert(data.disresponsiveList, data.to)
    end
  end,
}
local shehu_delay = fk.CreateTriggerSkill{
  name = "#dajubei__shehu_delay",
  mute = true,
  events = {fk.Damage, fk.CardUseFinished},
  can_trigger = function(self, event, target, player, data)
    if target == player then
      if event == fk.Damage then
        if not player.dead and data.card then
          local use_event = player.room.logic:getCurrentEvent():findParent(GameEvent.UseCard)
          if use_event then
            local use = use_event.data[1]
            if use.extra_data and use.extra_data.dajubei__shehu then
              return use.extra_data.dajubei__shehu[1] == player.id and
                table.find(use.extra_data.dajubei__shehu[2], function (id)
                  return player.room:getCardArea(id) == Card.Processing
                end)
            end
          end
        end
      elseif event == fk.CardUseFinished then
        return data.extra_data and data.extra_data.dajubei__shehu and
          table.find(data.extra_data.dajubei__shehu[2], function (id)
            return player.room:getCardArea(id) == Card.Processing
          end)
      end
    end
  end,
  on_cost = Util.TrueFunc,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local use_event = room.logic:getCurrentEvent():findParent(GameEvent.UseCard)
    if use_event then
      local use = use_event.data[1]
      if use.extra_data and use.extra_data.dajubei__shehu then
        local cards = table.filter(use.extra_data.dajubei__shehu[2], function (id)
          return room:getCardArea(id) == Card.Processing
        end)
        if #cards > 0 then
          if event == fk.Damage then
            --room:moveCardTo(cards, Card.PlayerHand, player, fk.ReasonJustMove, "dajubei__shehu", nil, true, player.id)
            local ids = room:askForPoxi(player, "shehu_delay", {
              { self.name, cards },
            })
            local to_get = table.filter(cards, function(id)
              return table.contains(ids, id)
            end)
            local to_throw = table.filter(cards, function(id)
              return not table.contains(ids, id)
            end)
            room:moveCardTo(to_get, Card.PlayerHand, player, fk.ReasonJustMove, self.name, "", true)
            room:moveCardTo(to_throw, Card.DiscardPile, nil, fk.ReasonJustMove, self.name, "", true)
          else
            room:moveCardTo(cards, Card.DiscardPile, nil, fk.ReasonJustMove)
          end
        end
      end
    end
  end,
}
yingong:addRelatedSkill(yingong_attackrange)
shehu:addRelatedSkill(shehu_delay)
yingong.CenterArea = true
liguang:addSkill(yingong)
liguang:addSkill(shehu)
Fk:loadTranslationTable{
  ["dajubei__liguang"] = "李广",
  ["#dajubei__liguang"] = "飞将军",
  ["illustrator:dajubei__liguang"] = "Hua Lu",
  ["designer:dajubei__liguang"] = "神棍德&好孩子系我",

  ["dajubei__yingong"] = "引弓",
  [":dajubei__yingong"] = "锁定技，一名角色的回合内，每有一张牌进入弃牌堆，你的攻击范围便+1，然后若所有其他角色均在你攻击范围内，你可使用中央区内的一张【杀】，然后你不能发动此技能直到你回合开始。",
  ["dajubei__shehu"] = "慑胡",
  [":dajubei__shehu"] = "回合技，当你使用【杀】指定一名角色为目标后，你可以亮出牌堆顶的X张牌（X为你与该角色的距离）。若此【杀】与亮出牌的花色均不同，"..
  "则不可被响应；此【杀】造成伤害后，你获得亮出牌中花色不重复的牌。",
  ["@dajubei__yingong-turn"]= "引弓",
  ["#djb__yingong-use"]= "引弓：你可以使用中央区的一张【杀】",
  ["@@dajubei__yingong"] = TT.colorString("引弓禁用", "red"),
  ["#dajubei__shehu-invoke"] = "慑胡：是否对 %dest 发动“慑胡”？",
  ["#dajubei__shehu_delay"] = "慑胡",

  ["$dajubei__yingong1"] = "嘎啦嘎啦",
  ["$dajubei__shehu1"] = "饮羽没石，虏骑慑服。",
  ["$dajubei__shehu2"] = "惮像蛮胡，驰射难中。",
  ["~dajubei__liguang"] = "此乃……将军不得侯者也……",
}


local tianfeng_jushou = General(extension, "dajubei__tianfengjushou", "qun", 3)
TT.loadGeneral(tianfeng_jushou, { name = "田丰沮授", reputation = "伴虎议徐", illustrator = "鹿田&兴游", designer = "夜洛无殇", cv = "淼龙&易大剧", dead = "身亡命殒……死欲速朽……" })
tianfeng_jushou.strategy = "scheme"
local yizhen = fk.CreateActiveSkill {
  name = "dajubei__yizhen",
  anim_type = "special",
  derived_piles = "$yizhen_pile",
  prompt = "#dajubei__yizhen",
  can_use = function (self, player, card, extra_data)
    local zhen = player:getPile("$yizhen_pile") or {}
    return player:usedSkillTimes(self.name, Player.HistoryPhase) < 1 and #zhen == 0
  end,
  card_filter = Util.FalseFunc,
  target_filter = Util.FalseFunc,
  on_use = function (self, room, effect)
    local player = room:getPlayerById(effect.from)
    player:drawCards(2, self.name)
    if player.dead or player:isNude() then return end
    local to_set = room:askForCard(player, 2, 2, true, self.name, false, nil, "#dajubei__yizhen-set")
    player:addToPile("$yizhen_pile", to_set, false, self.name)
  end,
}

local yizhen_trigger = fk.CreateTriggerSkill{
  name = "#dajubei__yizhen_trigger",
  mute = true,
  events = {fk.EventPhaseStart, fk.TargetConfirmed}, -- 保险起见还是变成目标后
  can_trigger = function (self, event, target, player, data)
    local zhen = player:getPile("$yizhen_pile") or {}
    if not player:hasSkill(self) or #zhen == 0 then return false end
    if event == fk.EventPhaseStart then
      return player == target and player.phase == Player.Start
    elseif event == fk.TargetConfirmed then
      return data.card.trueName == "slash" and target == player
    end
  end,
  on_cost = function (self, event, target, player, data)
    local room = player.room
    if event == fk.EventPhaseStart then
      room:notifySkillInvoked(player, self.name, "drawcard")
      player:broadcastSkillInvoke(yizhen.name, 1)
    else
      room:notifySkillInvoked(player, self.name, "offensive")
      player:broadcastSkillInvoke(yizhen.name, 2)
    end
    return true
  end,
  on_use = function (self, event, target, player, data)
    if player.dead then return end
    local room = player.room
    local id = room:askForCardChosen(player, player, { card_data = {{self.name, player:getPile("$yizhen_pile")}} }, self.name)
    room:moveCardTo(id, Card.DiscardPile, nil, fk.ReasonPutIntoDiscardPile, self.name, nil, true)
    local zhen = Fk:getCardById(id)
    if player.dead then return end
    if event == fk.EventPhaseStart and zhen.color == Card.Red then
      local to = room:askForChoosePlayers(player, table.map(room.alive_players, Util.IdMapper), 1, 1, "#yizhen-support", self.name, false)
      if to and to[1] then
        to = room:getPlayerById(to[1])
        if not to.dead then
          TT.recover(to, 1, self.name)
          to:drawCards(2, self.name)
        end
      end
    elseif event == fk.TargetConfirmed and zhen.color == Card.Black then
      room:sendLog{ type = "#yizhen-defence", from = data.from }
      room:delay(500)
      data.nullifiedTargets = table.map(room.players, Util.IdMapper)
      room:damage{
        from = player,
        to = room:getPlayerById(data.from),
        damage = 1,
        reason = self.name,
        damageType = fk.NormalDamage,
      }
    end
  end
}
yizhen:addRelatedSkill(yizhen_trigger)

tianfeng_jushou:addSkill(yizhen)

--- 找场上的所有马
---@param room AbstractRoom
---@return integer[]
local getHorses = function (room)
  local horses = {}
  for _, p in ipairs(room.alive_players) do
    for _, sub in ipairs{Card.SubtypeOffensiveRide, Card.SubtypeDefensiveRide} do
      local horse = p:getEquipments(sub)
      if #horse > 0 then
        for _, id in ipairs(horse) do
          table.insert(horses, id)
        end
      end
    end
  end
  return horses
end

local sijie = fk.CreateViewAsSkill{
  name = "dajubei__sijie",
  anim_type = "support",
  pattern = "peach",
  prompt = "#dajubei__sijie",
  interaction = function (self)
    local horses = getHorses(Fk:currentRoom())
    local all_choices = table.map(horses, function (id) return TT.getCardData(id, Fk:currentRoom()) end)
    local choices = table.map(all_choices, function (data) return data.name end)
    return TT.CardNameBox { choices = horses, all_choices = all_choices, }
  end,
  card_filter = Util.FalseFunc,
  view_as = function (self, cards)
    local id = self.interaction.data
    if not id then return end
    local peach = Fk:cloneCard("peach")
    peach.skillName = self.name
    peach:addSubcard(id)
    return peach
  end,
  enabled_at_play = Util.FalseFunc,
  enabled_at_response = function (self, player, response)
    return player.dying and #getHorses(Fk:currentRoom()) > 0
  end
}

local sijie_trigger = fk.CreateTriggerSkill{
  name = "#dajubei__sijie_trigger",
  anim_type = "negative",
  events = {fk.PreCardEffect},
  can_trigger = function(self, event, target, player, data)
    if player:hasSkill(self) and target and player ~= target then
      return data.card.name == "peach" and data.to == player.id
    end
  end,
  on_cost = Util.TrueFunc,
  on_use = function(self, event, target, player, data)
    table.insertIfNeed(data.nullifiedTargets, player.id)
  end,
}

sijie:addRelatedSkill(sijie_trigger)

tianfeng_jushou:addSkill(sijie)

Fk:loadTranslationTable{
  ["dajubei__yizhen"] = "疑阵",
  ["#dajubei__yizhen_trigger"] = "疑阵",
  [":dajubei__yizhen"] = "出牌阶段限一次，若你武将牌上没有牌，你可摸两张牌并将两张牌暗置于武将牌上。以下时机你需弃置一张暗置牌："
  .."当你成为【杀】的目标时→若此牌为黑色，该【杀】无效且你对【杀】的使用者造成一点伤害；"
  .."准备阶段→若此牌为红色，你令一名角色回复一点体力并摸两张牌。",
  ["#yizhen-support"] = "疑阵：请令一名角色回复1点体力并摸两张牌",
  ["#dajubei__yizhen"] = "疑阵：你可以发动“疑阵”，摸两张牌并将两张牌暗置于武将牌上。",
  ["#dajubei__yizhen-set"] = "疑阵：请选择一张牌暗置",
  ["$yizhen_pile"] = "疑阵",
  ["#yizhen-defence"] = "<b>疑阵：</b>：%from 使用的【杀】无效",
  ["dajubei__sijie"] = "死节",
  [":dajubei__sijie"] = "当你处于濒死状态时，你可将场上的坐骑牌当【桃】使用，且其他角色的【桃】对你无效。",
  ["#dajubei__sijie"] = "死节：你可以将场上坐骑牌当【桃】使用。",
  ["#dajubei__sijie_trigger"] = "死节",
}

local lier = General(extension, "dajubei__lier", "zhou", 3)
TT.loadGeneral(lier, { name = "李耳", illustrator = "lathander1987", designer = "拉普拉斯", })

local yingdao_trigger = fk.CreateTriggerSkill{
  name = "#dajubei__yingdao_trigger",
  mute = true,
  refresh_events = {fk.AfterAskForCardUse},
  can_refresh = function(self, event, target, player, data)
    return player:hasSkill(self) and target == player and player.phase == Player.NotActive
    and Fk:cloneCard(data.cardName).type == Card.TypeBasic
  end,
  on_refresh = function(self, event, target, player, data)
    local mark = player:getTableMark("@$dajubei__yingdao")
    if not (data.result and data.result.from == player.id) then
      table.insertIfNeed(mark, data.cardName)
    elseif table.contains(mark, data.cardName) then
      table.removeOne(mark, data.cardName)
    end
    player.room:setPlayerMark(player, "@$dajubei__yingdao", #mark > 0 and mark or 0)
  end,
}

local yingdao = fk.CreateViewAsSkill{
  name = "dajubei__yingdao",
  card_num = 0,
  card_filter = Util.FalseFunc,
  pattern = ".|.|.|.|.|basic",
  interaction = function()
    local all_names = U.getAllCardNames("b")
    local names = Self:getTableMark("@$dajubei__yingdao")
    local invoke_names = table.filter(U.getAllCardNames("b"), function (name)
      return table.contains(names, Fk:cloneCard(name).trueName)
    end)
    return U.CardNameBox { choices = invoke_names, all_choices = all_names }
  end,
  view_as = function(self, cards)
    if #cards ~= 0 or not self.interaction.data then return end
    local card = Fk:cloneCard(self.interaction.data)
    card.skillName = self.name
    return card
  end,
  before_use = function(self, player, use)
    local mark = player:getTableMark("@$dajubei__yingdao")
    table.removeOne(mark, use.card.name)
    player.room:setPlayerMark(player, "@$dajubei__yingdao", #mark > 0 and mark or 0)
  end,
  enabled_at_play = function(self, player)
    return #player:getTableMark("@$dajubei__yingdao") > 0
  end,
  enabled_at_response = function(self, player, response)
    return #player:getTableMark("@$dajubei__yingdao") > 0 and not response
  end,
}
yingdao:addRelatedSkill(yingdao_trigger)

local ConvertPlace = function(value)
  if value == Card.PlayerHand then
    return "hand"
  elseif value == Card.PlayerEquip then
    return "equip"
  elseif value == Card.PlayerJudge then
    return "judge"
  end
end

local guiben = fk.CreateTriggerSkill{
  name = "dajubei__guiben",
  frequency = Skill.Compulsory,
  events = {fk.CardUseFinished, fk.AfterCardsMove},
  can_trigger = function(self, event, target, player, data)
    if not player:hasSkill(self) then return end
    if event == fk.CardUseFinished then
      return target == player and #player:getTableMark("guiben_use-round") >= 3 and player:getMark("guiben1-round") == 0
    elseif #player:getTableMark("guiben_move-round") >= 3 and player:getMark("guiben2-round") == 0 then
      for _, move in ipairs(data) do
        if move.from and move.from == player.id then
          for _, info in ipairs(move.moveInfo) do
            return info.fromArea == Card.PlayerHand or info.fromArea == Card.PlayerEquip or info.fromArea == Card.PlayerJudge
          end
        elseif move.to and move.to == player.id then
          return move.toArea == Card.PlayerHand or move.toArea == Card.PlayerEquip or move.toArea == Card.PlayerJudge
        end
      end
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    if event == fk.CardUseFinished then
      room:addPlayerMark(player, "guiben1-round")
    else
      room:addPlayerMark(player, "guiben2-round")
    end
    local ids = {}
    if #room.draw_pile > 0 then
      table.insertIfNeed(ids, table.random(room.draw_pile))
    end
    if #room.discard_pile > 0 then
      local id = room:askForCardChosen(player, player, {card_data = {{"discard_pile", room.discard_pile}}}, self.name)
      table.insertIfNeed(ids, id)
    end
    if #table.filter(room.alive_players, function(p) return #p:getCardIds("ej") > 0 end) > 0 then
      local cards = {}
      for _, p in ipairs(room.alive_players) do
        if #p:getCardIds("ej") > 0 then
          table.insert(cards, {p.general, p:getCardIds("ej")})
        end
      end
      local id = room:askForCardChosen(player, player, {card_data = cards}, self.name)
      table.insertIfNeed(ids, id)
    end
    if #ids > 0 then
      room:obtainCard(player, ids, false, fk.ReasonPrey, player.id, self.name)
    end
  end,

  refresh_events = {fk.CardUsing, fk.AfterCardsMove},
  can_refresh = function(self, event, target, player, data)
    if event == fk.CardUsing then
      return target == player and player:hasSkill(self) and #player:getTableMark("guiben_use-round") < 3
    else
      if player:hasSkill(self) and #player:getTableMark("guiben_move-round") < 3 then
        for _, move in ipairs(data) do
          return (move.from and move.from == player.id) or (move.to and move.to == player.id)
        end
      end
    end
  end,
  on_refresh = function(self, event, target, player, data)
    if event == fk.CardUsing then
      local mark = player:getTableMark("guiben_use-round")
      table.insertIfNeed(mark, data.card.type)
      player.room:setPlayerMark(player, "guiben_use-round", mark)
    else
      for _, move in ipairs(data) do
        local mark = player:getTableMark("guiben_move-round")
        if move.from and move.from == player.id then
          for _, info in ipairs(move.moveInfo) do
            if info.fromArea == Card.PlayerHand or info.fromArea == Card.PlayerEquip or info.fromArea == Card.PlayerJudge then
              table.insertIfNeed(mark, ConvertPlace(info.fromArea))
            end
          end
        end
        if move.to and move.to == player.id then
          if move.toArea == Card.PlayerHand or move.toArea == Card.PlayerEquip or move.toArea == Card.PlayerJudge then
            table.insertIfNeed(mark, ConvertPlace(move.toArea))
          end
        end
        player.room:setPlayerMark(player, "guiben_move-round", mark)
      end
    end
  end
}

Fk:loadTranslationTable{
  ["@$dajubei__yingdao"] = "应道",
  ["discard_pile"] = "弃牌堆",
  ["dajubei__yingdao"] = "应道",
  [":dajubei__yingdao"] = "当你于回合外放弃使用基本牌后，则你下一次需要使用此牌名的基本牌时，可视为使用之。"..
  "<br />"..TT.colorString("注：本意自己濒死仅触发放弃使用【桃】", "#228B22"),
  ["dajubei__guiben"] = "归本",
  [":dajubei__guiben"] = "锁定技，一轮内，当你累计使用三种类型的牌后，或当你三个区域内的牌数量均发生变化后，若你于此轮未以此法获得过牌，则你获得弃牌堆和场上各一张牌，并从牌堆随机获得一张牌。",
}

lier:addSkill(yingdao)
lier:addSkill(guiben)

local arthas = General(extension, "djb1__arthas", "west", 4)
TT.loadGeneral(arthas, {
  name = "阿尔萨斯", illustrator = "暴雪", designer = "夜洛无殇", cv = "暴雪", dead = "我会回来的。"
})

local lich_king = General(extension, "djb2__arthas", "west", 4)
TT.loadGeneral(lich_king, {
  name = "阿尔萨斯", illustrator = "暴雪", designer = "夜洛无殇", cv = "暴雪", dead = "我会回来的。"
})
lich_king.hidden = true

local qinxin_tab = {"qinxinHeal", "qinxinPresent", "qinxinDraw", "qinxinPass","qinxinDesrtroy" ,"qinxinDiscard", "qinxinAttack", "qinxinTransform" }

local qinxin = fk.CreateTriggerSkill{
  name = "dajubei__qinxin",
  mute = true,
  events = {fk.Damaged},
  can_trigger = function(self, event, target, player, data)
    return player:hasSkill(self) and not target.dead
  end,
  on_cost = function (self, event, target, player, data)
    local room = player.room
    local mark = player:getMark("@dajubei__qinxin") -- @integer
    if type(mark) ~= "number" or mark < 1 or mark > 8 then return false end
    mark = qinxin_tab[mark]
    if mark == "qinxinHeal" then
      return target:isWounded() and room:askForSkillInvoke(player, self.name, data, "qinxinHeal-prompt:".. target.id)
    elseif mark == "qinxinDesrtroy" then
      if #target:getCardIds("he") >= 2 then
        if room:askForSkillInvoke(player, self.name, data, "qinxinDesrtroy-prompt:".. target.id) then
          local ids = room:askForCardsChosen(player, target, 2, 2, "he", self.name, "qinxinDesrtroy-prompt2:" .. target.id)
          if #ids == 2 then
            self.cost_data = ids
            return true
          end
        end
      end
    elseif mark == "qinxinDiscard" then
      if #player:getCardIds("he") >= 1 then
        local ids = room:askForDiscard(player, 1, 1, true,  self.name, true, nil, "qinxinDiscard-prompt:" .. target.id, true)
        if #ids == 1 then
          self.cost_data = ids
          return true
        end
      end
    elseif table.contains({"qinxinPresent", "qinxinDraw", "qinxinPass", "qinxinAttack", "qinxinTransform"}, mark) then
      return room:askForSkillInvoke(player, self.name, data, mark.. "-prompt:" .. target.id)
    end
  end,
  on_use = function (self, event, target, player, data)
    local room = player.room
    local mark = player:getMark("@dajubei__qinxin") -- @integer
    room:notifySkillInvoked(player, self.name, "switch")
    player:broadcastSkillInvoke(self.name, mark)
    local to_set
    if mark + 1 <= 8 then
      to_set = mark + 1
    else
      to_set = TT.colorString("无法回头！", "#45D7DF")
      room:notifySkillInvoked(player, self.name, "big")
    end
    room:setPlayerMark(player, "@dajubei__qinxin", to_set)

    mark = qinxin_tab[mark]
    if mark == "qinxinHeal" then
      TT.recover(target, 1, self.name)
    elseif mark == "qinxinDesrtroy" then
      room:throwCard(table.filter(self.cost_data, function (id) return room:getCardOwner(id) == target end), self.name, target, player)
    elseif mark == "qinxinDiscard" then
      room:throwCard(table.filter(self.cost_data, function (id) return room:getCardOwner(id) == player end), self.name, player, player)
    elseif mark == "qinxinPresent" then
      room:drawCards(target, 2, self.name)
    elseif mark == "qinxinDraw" then
      room:drawCards(player, 1, self.name)
    elseif mark == "qinxinPass" then
      -- do nothing
    elseif mark == "qinxinAttack" then
      TT.damage(player, target, 1, self.name)
    elseif mark == "qinxinTransform" then
      room:handleAddLoseSkills(player, "-"..self.name)
      if player.general == arthas.name then
        player.general = lich_king.name
        player.room:broadcastProperty(player, "general")
      end
      if player.deputyGeneral == arthas.name then
        player.deputyGeneral = lich_king.name
        player.room:broadcastProperty(player, "deputyGeneral")
      end
      room:handleAddLoseSkills(player, "dajubei__ansha")
      if player.dead then return end
      local death_knights = player:getPile("ansha_death_knights")
      if #death_knights > 0 then
        local to_gain = table.filter(death_knights, function (id)
          return Fk:getCardById(id).name == "frostmourne"
        end)
        room:obtainCard(player, to_gain, true, fk.ReasonJustMove, player.id, self.name)
        if table.contains(player:getCardIds("h"), to_gain[1]) then
          room:useCard {
            from = player.id,
            tos = { {player.id} },
            card = Fk:getCardById(to_gain[1]),
          }
        end
      end
    end
  end,

  refresh_events = {fk.EventAcquireSkill},
  can_refresh = function (self, event, target, player, data)
    return player:hasSkill(self) and data == self
  end,
  on_refresh = function (self, event, target, player, data)
    player.room:setPlayerMark(player, "@dajubei__qinxin", 1)
  end
}

Fk:loadTranslationTable{
  ["qinxinHeal-prompt"] = "%src 受到了伤害，你是否想要发动“侵心”，令其回复1点体力？",
  ["qinxinDesrtroy-prompt"] = "%src 受到了伤害，你是否想要发动“侵心”，弃置其两张牌？",
  ["qinxinDesrtroy-prompt2"] = "侵心：请弃置 %src 两张牌",
  ["qinxinDiscard-prompt"] = "%src 受到了伤害，你是否想要发动“侵心”，弃置一张牌？",
  ["qinxinPresent-prompt"] = "%src 受到了伤害，你是否想要发动“侵心”，令其摸两张牌？",
  ["qinxinDraw-prompt"] = "%src 受到了伤害，你是否想要发动“侵心”，摸一张牌？",
  ["qinxinPass-prompt"] = "%src 受到了伤害，你是否想要发动“侵心”，发动后什么都不做？",
  ["qinxinAttack-prompt"] = "%src 受到了伤害，你是否想要发动“侵心”，对其造成1点伤害？",
  ["qinxinTransform-prompt"] = "%src 受到了伤害，你是否想要发动“侵心”，获得“暗煞”？",
}
Fk:loadTranslationTable{
  ["dajubei__qinxin"] = "侵心",
  [":dajubei__qinxin"] = "转换技，当一名角色受到伤害后，你可以①令其回复1点体力；②令其摸两张牌；③摸一张牌；④什么也不做；⑤弃置其两张牌；⑥弃置一张牌；⑦对其造成1点伤害；⑧失去“侵心”，获得“暗煞”，获得【霜之哀伤】并使用之。",
  ["@dajubei__qinxin"] = "侵心",
}

local death_knight_list = { "frostmourne", "anti_magic_shell", "army_of_the_dead", "death_and_decay", "death_coil", "death_grip", "doom_pact", "obliterate" }

local ansha = fk.CreateTriggerSkill{
  name = "dajubei__ansha",
  anim_type = "drawcard",
  derived_piles = "ansha_death_knights",
  events = {fk.EventPhaseStart},
  can_trigger = function(self, event, target, player, data)
    if player:hasSkill(self) then
      return player == target and player.phase == Player.Start
    end
  end,
  on_cost = function (self, event, target, player, data)
    local room = player.room
    local death_knights = player:getPile("ansha_death_knights")
    if #death_knights > 0 then
      local random_knights = table.random(death_knights, math.min(#death_knights, 3))
      local id = room:askForCardsChosen(player, player, 1, 1, {card_data = {{"ansha_death_knights", random_knights}}}, self.name, "ansha-prompt")
      if #id == 1 then
        self.cost_data = id
        return true
      end
    end
  end,
  on_use = function (self, event, target, player, data)
    local room = player.room
    room:obtainCard(player, self.cost_data, true, fk.ReasonJustMove, player.id, self.name)
  end,

  refresh_events = {fk.EventAcquireSkill, fk.AfterCardsMove},
  can_refresh = function (self, event, target, player, data)
    if not player:hasSkill(self) then return end
    if event == fk.EventAcquireSkill then
      return data == self
    else
      return true
    end
  end,
  on_refresh = function (self, event, target, player, data)
    local room = player.room
    if event == fk.EventAcquireSkill then
      --local death_knights = table.filter(room.void, function(id) return table.contains(death_knight_list, Fk:getCardById(id).name) end)
      local death_knights_pile = table.map(death_knight_list, function (name)
        return {name, Card.Spade, table.indexOf(death_knight_list, name)} end)
      local death_knights = U.prepareDeriveCards(room, death_knights_pile, "ansha_death_knights")
      if #death_knights > 0 then
        player:addToPile("ansha_death_knights", death_knights)
      end
    else
      local new_move = {}
      for _, move in ipairs(data) do
        if move.toArea == Card.DiscardPile then
          for _, info in ipairs(move.moveInfo) do
            local cid = info.cardId
            if table.contains(death_knight_list, Fk:getCardById(cid).name) and room:getCardArea(cid) == Card.DiscardPile then
              table.insert(new_move, cid)
            end
          end
          if #new_move > 0 then
            room:moveCardTo(new_move, Card.PlayerSpecial, player, fk.ReasonJustMove, self.name, "ansha_death_knights", true, player.id)
          end
        end
      end
    end
  end,
}
TT.loadSkill(ansha, {
  name = "暗煞",
  detial = "",
  voices = {"巫妖王给了我真正的力量！", "这个“黑暗”到底是谁？"}
})

Fk:loadTranslationTable{
  ["dajubei__ansha"] = "暗煞",
  [":dajubei__ansha"] = "锁定技，准备阶段，你从死亡骑士牌堆中"..TT.hrefString("发现", "tuntian_explore").."一张牌；死亡骑士牌进入弃牌堆时，改为洗回死亡骑士牌堆。",
  ["ansha_death_knights"] = "死亡骑士",
  ["ansha-prompt"] = "暗煞：请选择一张死亡骑士牌获得。",
  ["tuntian_explore"] = "随机观看三张，选择其中指定的张数获得。",
}

lich_king:addSkill(ansha)
arthas:addSkill(qinxin)
arthas:addRelatedSkill("dajubei__ansha")

local mengda = General(extension, "dajubei__mengda", "shu", 4)
mengda.subkingdom = "wei"
TT.loadGeneral(mengda, { name = "孟达", illustrator = "六道目", reputation = "枭蛇反复", designer = "二阶堂芽衣", dead = "司马老贼害我，诸葛老贼误我……" })

-- 场上的牌颜色是否均衡
local function isBalance(room)
  local card_map = { ["red"] = {}, ["black"] = {} }
  for _, p in ipairs(room.alive_players) do
    for _, id in ipairs(p:getCardIds("ej")) do
      local card = Fk:getCardById(id)
      table.insert(card_map[card:getColorString()], id)
    end
  end
  return #card_map["red"] == #card_map["black"]
end

local guanshi = fk.CreateViewAsSkill{
  name = "dajubei__guanshi",
  anim_type = "drawcard",
  pattern = "ex_nihilo,nullification",
  prompt = "#dajubei__guanshi",
  expand_pile = function (self, player)
    return player:getTableMark("guanshi_cards")
  end,
  interaction = function (self)
    local room = Fk:currentRoom()
    local choices = {}
    for _, p in ipairs(room.players) do
      table.insertTableIfNeed(choices, p:getCardIds("ej"))
    end
    local all_choices = table.map(choices, function (id) return TT.getCardData(id, Fk:currentRoom()) end)
    return TT.CardNameBox { choices = choices, all_choices = all_choices, }
  end,
  card_filter = function (self, to_select, selected)
    if #selected > 0 or self.interaction.data == nil then return false end
    local mark = Self:getTableMark("guanshi_cards")
    local guanshi_cards = table.filter(U.getAllCardNames("t"), function (name)
      return string.find(name, "ex_nihilo") or string.find(name, "nullification")
    end)
    local enable_cards = U.getViewAsCardNames(Self, self.name, guanshi_cards)
    local name = Fk:getCardById(to_select).name
    return table.contains(mark, to_select) and table.contains(enable_cards, name)
  end,
  view_as = function (self, cards)
    if #cards == 1 and self.interaction.data ~= nil then
      local card = Fk:cloneCard(Fk:getCardById(cards[1]).name)
      card:addSubcard(self.interaction.data)
      card.skillName = self.name
      return card
    end
  end,
  enabled_at_play = function (self, player)
    return player:getMark("@@guanshi_forbidden") == 0 and player:usedSkillTimes(self.name, Player.HistoryTurn) < 1
  end,
  enabled_at_response = function (self, player, response)
    return player:getMark("@@guanshi_forbidden") == 0 and player:usedSkillTimes(self.name, Player.HistoryTurn) < 1
  end,
  after_use = function (self, player, use)
    local room = player.room
    if not isBalance(room) then
      room:setPlayerMark(player, "@@guanshi_forbidden", 1)
    end
  end,
}
TT.loadSkill(guanshi, {
  name = "观势",
  detial = "每回合限一次，你可以将场上一张牌当【无中生有】或【无懈可击】使用，然后你不能再发动此技能，直到场上两种颜色的牌数量相同。",
  voices = {"腹中有粮则脊自直，非节盈之。", "气节？可当粟米果腹乎！"}
})

local guanshi_refresh = fk.CreateTriggerSkill {
  name = "#dajubei__guanshi_refresh",
  mute = true,

  refresh_events = {fk.EventAcquireSkill, fk.AfterCardsMove},
  can_refresh = function (self, event, target, player, data)
    local room = player.room
    if not player:hasSkill(self) then return end
    if event == fk.EventAcquireSkill then
      return data == guanshi
    else
      return isBalance(room) and player:getMark("@@guanshi_forbidden") > 0
    end
  end,
  on_refresh = function (self, event, target, player, data)
    local room = player.room
    if event == fk.EventAcquireSkill then
      local guanshi_cards = table.filter(U.getAllCardNames("t"), function (name)
        return string.find(name, "ex_nihilo") or string.find(name, "nullification")
      end)
      local mark = {room:printCard(guanshi_cards[1]).id, room:printCard(guanshi_cards[2]).id}
      room:setPlayerMark(player, "guanshi_cards", mark)
    else
      room:setPlayerMark(player, "@@guanshi_forbidden", 0)
    end
  end,
}

TT.loadSkill(guanshi_refresh, {
  name = "观势",
})
guanshi:addRelatedSkill(guanshi_refresh)

Fk:loadTranslationTable{
  ["dajubei__guanshi"] = "观势",
  [":dajubei__guanshi"] = "回合技，你可将场上一张牌当【无中生有】或【无懈可击】使用，然后你不能再发动此技能，直到场上两种颜色的牌数量相同。",
  ["#dajubei__guanshi"] = "观势：你可以将场上的一张牌当【无中生有】或【无懈可击】使用。",
  ["@@guanshi_forbidden"] = "观势"..TT.colorString("禁", "red"),
  ["guanshi_cards"] = "观势",
}

mengda:addSkill(guanshi)

local panxuan = fk.CreateViewAsSkill {
  name = "dajubei__panxuan",
  anim_type = "support",
  prompt = "#dajubei__panxuan",
  pattern = ".|.|.|.|.|basic",
  interaction = function (self)
    local all_choices = U.getAllCardNames("b")
    local choices = U.getViewAsCardNames(Self, self.name, all_choices)
    return U.CardNameBox { choices = choices, all_choices = all_choices, }
  end,
  card_filter = Util.FalseFunc,
  view_as = function (self, cards)
    if self.interaction.data then
      local card = Fk:cloneCard(self.interaction.data)
      card.skillName = self.name
      return card
    end
  end,
  before_use = function (self, player, use)
    local room = player.room
    local target, card = U.askForChooseCardsAndPlayers(room, player, 1, 1,
      table.map(room:getOtherPlayers(player), Util.IdMapper), 1, 1, nil, "panxuan-choose", self.name, false)
    if #target == 1 and #card == 1 then
      local obtainer = room:getPlayerById(target[1])
      room:obtainCard(obtainer, card, false, fk.ReasonGive, player.id, self.name)
      if not player.dead and not obtainer:isKongcheng() then
        local enable_cards = table.filter(obtainer:getCardIds("h"), function (id)
          return Fk:getCardById(id).trueName == use.card.trueName
        end)
        local op_card, choice = U.askforChooseCardsAndChoice(player, enable_cards, {"OK"},
          self.name, "panxuan-use:"..obtainer.id, {"Cancel"}, 1, 1, obtainer:getCardIds("h"))
        if choice == "Cancel" then
          if #obtainer:getCardIds("ej") > 0 then
            local ob_card = room:askForCardsChosen(player, obtainer, 1, 1, "ej", self.name, "panxuan-pery:"..obtainer.id)
            if #ob_card == 1 then
              room:obtainCard(player, ob_card, false, fk.ReasonPrey, player.id, self.name)
            end
          end
          return self.name
        elseif #op_card > 0 then
          use.card = Fk:getCardById(op_card[1])
          return nil
        end
      end
    end
  end,
  enabled_at_play = function (self, player)
    return player:usedSkillTimes(self.name, Player.HistoryTurn) < 1 and not player:isNude()
  end,
  enabled_at_response = function (self, player, response)
    return player:usedSkillTimes(self.name, Player.HistoryTurn) < 1 and not player:isNude()
  end,
}

TT.loadSkill(panxuan, {
  name = "叛旋",
  detial = "每回合限一次，当你需要使用基本牌时，你可以交给一名其他角色一张牌，然后你观看其手牌并可使用其中的对应牌。"
  .."若你未使用，你获得其场上一张牌。",
})

Fk:loadTranslationTable {
  ["dajubei__panxuan"] = "叛旋",
  [":dajubei__panxuan"] = "回合技，当你需要使用基本牌时，你可以交给一名其他角色一张牌，然后你观看其手牌并可使用其中的对应牌。",
  ["#dajubei__panxuan"] = "你是否想要发动“叛旋”，视为使用一张基本牌？",
  ["panxuan-choose"] = "叛旋：请选择一张牌，交给一名其他角色",
  ["panxuan-use"] = "叛旋：请选择一张对应牌使用，或点取消获得 %src 场上一张牌",
  ["panxuan-pery"] = "叛旋：请选择 %src 场上的一张牌获得",
}

mengda:addSkill(panxuan)

local yanghu = General(extension, "dajubei__yanghu", "wei", 4)
TT.loadGeneral(yanghu, { name = "羊祜", illustrator = "鬼画府", reputation = "遗策定西晋", designer = "可爱的tjk000" })
yanghu.strategy = "schemecourage"

local suiyu = fk.CreateTriggerSkill {
  name = "dajubei__suiyu",
  anim_type = "drawcard",
  events = {fk.CardUseFinished},
  can_trigger = function (self, event, target, player, data)
    if not player:hasSkill(self) then return end
    return table.contains(U.getActualUseTargets(player.room, data, event), player.id)
    and (not player.room.current or player.room.current ~= player)
  end,
  on_use = function (self, event, target, player, data)
    local room = player.room
    local from = room:getPlayerById(data.from)
    if not from or from.dead then return end
    room:drawCards(from, 1, self.name)
    if not (from.dead or from:isKongcheng() or from == player) then
      local present = room:askForCard(from, 1, 1, false, self.name, false, nil, "suiyu-give:"..from.id)
      if present and #present == 1 then
        room:obtainCard(player, present, false, fk.ReasonGive, from.id, self.name)
      end
    end
  end
}
--TT.loadSkill(suiyu, { name = "绥御", detial = "一张指定你为目标的牌结算后，若使用者手牌数大于你，你可以令其摸一张牌并交给你一张牌。"})
yanghu:addSkill(suiyu)

Fk:loadTranslationTable {
  ["dajubei__suiyu"] = "绥御",
  [":dajubei__suiyu"] = "你的回合外，当目标为你的牌结算后，你可令使用者摸一张牌并交给你一张牌。",
  ["suiyu-give"] = "绥御：请选择一张牌交给 %src",
}

local zoufa = fk.CreateActiveSkill {
  name = "dajubei__zoufa",
  anim_type = "offensive",
  min_card_num = 1,
  can_use = function (self, player, card, extra_data)
    return player:usedSkillTimes(self.name, Player.HistoryPhase) < (1 + player:getMark("dajubei__zoufa-phase"))
  end,
  card_filter = function (self, to_select, selected, selected_targets)
    if #selected == 0 then
      return true
    else
      local cards = table.map(selected, Util.Id2CardMapper)
      local suits = table.map(cards, function(c) return c.suit end)
      return not table.contains(suits, Fk:getCardById(to_select).suit)
    end
  end,
  target_num = 1,
  target_filter = function (self, to_select, selected, selected_cards, card, extra_data, player)
    if #selected < 1 then
      return to_select ~= player.id
    else
      return false
    end
  end,
  on_use = function (self, room, effect)
    local function getSuitNum(cardIds)
      local cards = table.map(cardIds, Util.Id2CardMapper)
      local suits = {}
      for _, c in ipairs(cards) do
        table.insertIfNeed(suits, c.suit)
      end
      return #suits
    end
    local cards = effect.cards
    local player = room:getPlayerById(effect.from)
    local target = room:getPlayerById(effect.tos[1])
    room:throwCard(cards, self.name, player, player)
    if target.dead then return end
    local toHit = true
    if not target:isKongcheng() then
      local hand_cards = target:getCardIds("h")
      if getSuitNum(hand_cards) > getSuitNum(cards) then
        toHit = false
      end
      room:showCards(hand_cards, target)
    end
    if toHit then
      if not target.dead then
        room:damage {
          from = player,
          to = target,
          damage = 1,
          skillName = self.name,
        }
      end
    else
      local able_players = room:getOtherPlayers(player)
      if #able_players > 0 then
        local beneficiary = room:askForChoosePlayers(player, table.map(able_players, Util.IdMapper), 1, 1, "zoufa-choose", self.name, false)
        if beneficiary and #beneficiary == 1 then
          room:setPlayerMark(player, "dajubei__zoufa-phase", 1) -- 再起！
          cards = table.filter(cards, function (id)
            return room:getCardArea(id) == Card.DiscardPile
          end)
          room:obtainCard(beneficiary[1], cards, false, fk.ReasonPrey, player.id, self.name)
        end
      end
    end
  end,
}
yanghu:addSkill(zoufa)

Fk:loadTranslationTable {
  ["dajubei__zoufa"] = "奏伐",
  [":dajubei__zoufa"] = "出牌阶段限一次，你可弃置任意张花色各不同的牌并展示一名其他角色的手牌，若其手牌花色数不大于X，你对其造成1点伤害；否则，你令一名其他角色获得弃置的牌，且本阶段内“奏伐”改为“出牌阶段限两次”（X为你以此法弃置的牌的花色数）。",
  ["zoufa-choose"] = "奏伐：请令一名其他角色获得本次弃置的牌",
}

return extension
